#pragma once

#include <vector>
#include <map>
#include <complex>


class CGraphBase
{
public:
	CGraphBase(void){
		_firstNodeId = -1;
		_lastNodeId = -1;
	};
	virtual ~CGraphBase(void){};

	struct Edge
	{
		int _from;
		int	_to;

		Edge() : _from(0), _to(0) {
		};

		Edge( int from, int to ) : _from(from), _to(to) {
		};

		bool operator == ( const Edge& e ) const{
			return _from == e._from && _to == e._to;
		};
	};

	struct ATWLE_NODE
	{
		// Variables of ATWLE
		int		es;		// error status {0, 1, 2}
		bool	marked;	// marked or not
		int		tag;	//  tag {0, 1, 2, 3, 4}
		bool	is_leader;
		bool	finished;

		ATWLE_NODE(){
			es			= 0;
			marked		= false;
			tag			= 0;
			is_leader	= false;
			finished	= false;
		};

	};

	struct SCHD
	{
		int clock;
		SCHD(){
			clock = -1;
		};
	};

	struct NodeInfo
	{
		int	  _id;
		float _x; // 0 - 10000.0f
		float _y; // 0 - 10000.0f
		bool  _bFixed;
		
		std::vector< int >	_inputs;
		std::vector< int >	_outputs;

		NodeInfo(){
			Clear();
		};

		void Clear(){
			_id = GenerateId();
			_y = (float)(100+::rand() % 7000);
			_x = (float)(::rand() % 8000);
			_bFixed = false;
		};

		int GenerateId(){
			static int id = 0;
			return id++;
		};

		ATWLE_NODE an;
		SCHD schd;
	};

	void Clear();

	void AddEdge( int from, int to );
	void DeleteNode( int id );

	void AddNodeByXY( float x, float y,  CRect rectRange );
	int GetNodeIdByXY( float x, float y, CRect rectRange );
	void SetNodeIdByXY( int id, float x, float y, CRect rectRange );

	std::map< int, NodeInfo >	_mapNodeInfo;
	std::vector< Edge >			_edges;

	int _firstNodeId;
	int _lastNodeId;

	bool ParseString( std::string str );
	int CalculateRouteCount();

	bool CalculateRouteCount_Step( std::vector<int>& vectNode, 
										   std::vector<Edge>& vectScannedEdges, 
										   int& iTotalRoute, 
										   int& iRestRoute );

	bool AtwleStep();

	void CalcClock();
	int CGraphBase::SetNodeClock( int index );

protected:

	// ATWLE functions
	
	bool IsA1( const NodeInfo& ni ) const;
	bool IsA2( const NodeInfo& ni ) const;
	bool IsA3( const NodeInfo& ni ) const;
	bool IsA4( const NodeInfo& ni ) const;
	bool IsA5( const NodeInfo& ni ) const;
	bool IsA6( const NodeInfo& ni ) const;

	void A1( NodeInfo& ni ) const;
	void A2( NodeInfo& ni ) const;
	void A3( NodeInfo& ni ) const;
	void A4( NodeInfo& ni ) const;
	void A5( NodeInfo& ni ) const;
	void A6( NodeInfo& ni ) const;
	
	std::vector<int> N( const NodeInfo& ni ) const;
	std::vector<int> U( const NodeInfo& ni ) const;

	int Delta_Tag( const NodeInfo& ni1, const NodeInfo& ni2 ) const;
	int Delta_ES( const NodeInfo& ni1, const NodeInfo& ni2 ) const;
	std::vector<int> Chldrn( const NodeInfo& ni ) const;
	std::vector<int> Parents( const NodeInfo& ni ) const;
	bool Is_Child( const NodeInfo& ni ) const;

	bool Finished( const NodeInfo& ni ) const;
	bool Clean( const NodeInfo& ni ) const;
	bool Valid( const NodeInfo& ni ) const;
	bool Error( const NodeInfo& ni ) const;
	bool Can_Reset( const NodeInfo& ni ) const;
	bool Can_Inc_Err_St( const NodeInfo& ni ) const;
	bool Clear( const NodeInfo& ni ) const;

};

class CMyGraph : public CGraphBase
{
public:
	CMyGraph(void){};
	virtual ~CMyGraph(void){};

#ifdef _WINDOWS

	void PaintToDC( CDC* pDC, CRect rectRange );
	void PaintEdgeConnecting( CDC* pDC, int connectingFromId, int x, int y, CRect rectClient );
	void DrawTriangle( CDC* pDC, CRect rectRange, int from, int to );

#endif

	bool UpdateNodeInfo();
};
